﻿using System;
using System.Security.Cryptography;
using System.Text;

namespace Core
{
    public enum EHashAlgorithm
    {
        // Md5,
        SHA1 = 1,
        SHA256,
        SHA384,
        SHA512,
        Crc32,
    }

    public static partial class Utils
    {
        /// <summary>
        /// 计算Hash
        /// </summary>
        public static class Hash
        {
            // private static readonly StringBuilder Builder = new();

            // /// <summary>
            // /// 字节数组转换为16进制表示的字符串
            // ///
            // /// 与下面方式效果一样
            // /// BitConverter.ToString(buf).Replace("-", "");
            // /// </summary>
            // /// <param name="byteHash"></param>
            // /// <returns></returns>
            // public static string ToHexString(byte[] byteHash)
            // {
            //     if (byteHash == null || byteHash.Length == 0) return string.Empty;
            //
            //     Builder.Clear();
            //     foreach (var t in byteHash)
            //     {
            //         Builder.Append(t.ToString("X2"));
            //     }
            //
            //     return Builder.ToString();
            // }

            private static HashAlgorithm Get(EHashAlgorithm eAlgorithm)
            {
                //algorithm = new MD5CryptoServiceProvider();
                //algorithm = new SHA1CryptoServiceProvider();
                //algorithm = new SHA256CryptoServiceProvider();
                //algorithm = new SHA384CryptoServiceProvider();
                //algorithm = new SHA512CryptoServiceProvider();

                HashAlgorithm algorithm = eAlgorithm switch
                {
                    // EHashAlgorithm.Md5 => MD5.Create(),
                    EHashAlgorithm.SHA1 => SHA1.Create(),
                    EHashAlgorithm.SHA256 => SHA256.Create(),
                    EHashAlgorithm.SHA384 => SHA384.Create(),
                    EHashAlgorithm.SHA512 => SHA512.Create(),
                    EHashAlgorithm.Crc32 => new Crc32(),
                    _ => null
                };

                return algorithm;
            }

            /// <summary>
            /// 计算字符串Hash值
            /// </summary>
            /// <param name="content"></param>
            /// <param name="eAlg"></param>
            /// <returns></returns>
            public static string DoText(string content, EHashAlgorithm eAlg = EHashAlgorithm.Crc32)
            {
                byte[] hashBytes;

                var bytes = Encoding.UTF8.GetBytes(content);
                using (var alg = Get(eAlg))
                {
                    hashBytes = alg.ComputeHash(bytes);
                }

                return BitConverter.ToString(hashBytes).Replace("-", "").ToLowerInvariant();
            }

            /// <summary>
            /// 计算字符串2重Hash值
            /// </summary>
            /// <param name="content"></param>
            /// <param name="eAlg"></param>
            /// <returns></returns>
            public static string DoTextD(string content, EHashAlgorithm eAlg = EHashAlgorithm.Crc32)
            {
                var code1 = DoText(content, eAlg);
                var code2 = DoText(code1, eAlg);
                return code2;
            }

            /// <summary>
            /// 计算文件的Hash值
            /// </summary>
            /// <param name="filePath"></param>
            /// <param name="eAlg"></param>
            /// <returns></returns>
            public static string DoFile(string filePath, EHashAlgorithm eAlg = EHashAlgorithm.Crc32)
            {
                if (System.IO.File.Exists(filePath) == false) return string.Empty;

                try
                {
                    using var alg = Get(eAlg);
                    using var fs = System.IO.File.OpenRead(filePath);
                    var hashBytes = alg.ComputeHash(fs);
                    return BitConverter.ToString(hashBytes).Replace("-", "").ToLowerInvariant();
                }
                catch (Exception ex)
                {
                    log.err(ex);
                }

                return string.Empty;
            }
        }
    }
}